/****************************************************************
 * Fulguro
 * Copyright (C) 2004 Christophe Clienti
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 ***************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <flgrCoreData.h>
#include <flgrCoreDataIO.h>
#include <flgrCoreSlideWindow.h>
#include <flgrCoreNhbManage.h>
#include <flgrCoreCopy.h>
#include <flgrCoreDispatch.h>

#include <flgrCoreArithVector.h>
#include <flgrArith.h>

#include <flgrDataToolsStaticFifo.h>

#include <flgrMorphoKerOp.h>
#include <flgrMorphoBase.h>
#include <flgrMorphoGeodesy.h>

/*!
 * \defgroup group_fulguro_core_morpho_geo Geodesic operations
 * \ingroup group_fulguro_morpho
 * \brief Geodesic operations
 * @{
 */


/***************************************************************************************************/
/***************************************************************************************************/
/************************************************ 1D ***********************************************/
/***************************************************************************************************/
/***************************************************************************************************/

////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
#define FLGR_MACRO_GEODESIC_DILATE_1D(dtype)		\
  flgr1d_dilate_##dtype(imgdest,imgMarker,nhb);		\
  flgr1d_arith_inf_##dtype(imgdest,imgMask,imgdest)

void flgr1d_geodesic_dilate_fgBIT(FLGR_Data1D *imgdest, FLGR_Data1D *imgMarker, FLGR_Data1D *imgMask, FLGR_Data1D *nhb) {
  FLGR_MACRO_GEODESIC_DILATE_1D(fgBIT);
}
void flgr1d_geodesic_dilate_fgUINT8(FLGR_Data1D *imgdest, FLGR_Data1D *imgMarker, FLGR_Data1D *imgMask, FLGR_Data1D *nhb) {
  FLGR_MACRO_GEODESIC_DILATE_1D(fgUINT8);
}
void flgr1d_geodesic_dilate_fgUINT16(FLGR_Data1D *imgdest, FLGR_Data1D *imgMarker, FLGR_Data1D *imgMask, FLGR_Data1D *nhb) {
  FLGR_MACRO_GEODESIC_DILATE_1D(fgUINT16);
}
void flgr1d_geodesic_dilate_fgUINT32(FLGR_Data1D *imgdest, FLGR_Data1D *imgMarker, FLGR_Data1D *imgMask, FLGR_Data1D *nhb) {
  FLGR_MACRO_GEODESIC_DILATE_1D(fgUINT32);
}
void flgr1d_geodesic_dilate_fgINT8(FLGR_Data1D *imgdest, FLGR_Data1D *imgMarker, FLGR_Data1D *imgMask, FLGR_Data1D *nhb) {
  FLGR_MACRO_GEODESIC_DILATE_1D(fgINT8);
}
void flgr1d_geodesic_dilate_fgINT16(FLGR_Data1D *imgdest, FLGR_Data1D *imgMarker, FLGR_Data1D *imgMask, FLGR_Data1D *nhb) {
  FLGR_MACRO_GEODESIC_DILATE_1D(fgINT16);
}
void flgr1d_geodesic_dilate_fgINT32(FLGR_Data1D *imgdest, FLGR_Data1D *imgMarker, FLGR_Data1D *imgMask, FLGR_Data1D *nhb) {
  FLGR_MACRO_GEODESIC_DILATE_1D(fgINT32);
}
void flgr1d_geodesic_dilate_fgFLOAT32(FLGR_Data1D *imgdest, FLGR_Data1D *imgMarker, FLGR_Data1D *imgMask, FLGR_Data1D *nhb) {
  FLGR_MACRO_GEODESIC_DILATE_1D(fgFLOAT32);
}
void flgr1d_geodesic_dilate_fgFLOAT64(FLGR_Data1D *imgdest, FLGR_Data1D *imgMarker, FLGR_Data1D *imgMask, FLGR_Data1D *nhb) {
  FLGR_MACRO_GEODESIC_DILATE_1D(fgFLOAT64);
}
////////////////////////////////////////////////////////////////////////////
/*! Compute Geodesic Dilation
 *  @param imgdest : image output
 *  @param imgMarker : marker image input
 *  @param imgMask : mask image input
 *  @param nhb : neighborhood definition
 *  @returns FLGR_RET_OK, ...
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr1d_geodesic_dilate(FLGR_Data1D *imgdest, FLGR_Data1D *imgMarker, FLGR_Data1D *imgMask, FLGR_Data1D *nhb) {

  FLGR_DECLARE_FUNCTION;

  if((imgdest==NULL) || (imgMarker==NULL) || (imgMask==NULL) || (nhb==NULL)) {
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  FLGR_DISPATCH_PROCEDURE(imgdest->type,flgr1d_geodesic_dilate,imgdest,imgMarker,imgMask,nhb);
}

////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
#define FLGR_MACRO_GEODESIC_ERODE_1D(dtype)		\
  flgr1d_erode_##dtype(imgdest,imgMarker,nhb);		\
  flgr1d_arith_sup_##dtype(imgdest,imgMask,imgdest)

void flgr1d_geodesic_erode_fgBIT(FLGR_Data1D *imgdest, FLGR_Data1D *imgMarker, FLGR_Data1D *imgMask, FLGR_Data1D *nhb) {
  FLGR_MACRO_GEODESIC_ERODE_1D(fgBIT);
}
void flgr1d_geodesic_erode_fgUINT8(FLGR_Data1D *imgdest, FLGR_Data1D *imgMarker, FLGR_Data1D *imgMask, FLGR_Data1D *nhb) {
  FLGR_MACRO_GEODESIC_ERODE_1D(fgUINT8);
}
void flgr1d_geodesic_erode_fgUINT16(FLGR_Data1D *imgdest, FLGR_Data1D *imgMarker, FLGR_Data1D *imgMask, FLGR_Data1D *nhb) {
  FLGR_MACRO_GEODESIC_ERODE_1D(fgUINT16);
}
void flgr1d_geodesic_erode_fgUINT32(FLGR_Data1D *imgdest, FLGR_Data1D *imgMarker, FLGR_Data1D *imgMask, FLGR_Data1D *nhb) {
  FLGR_MACRO_GEODESIC_ERODE_1D(fgUINT32);
}
void flgr1d_geodesic_erode_fgINT8(FLGR_Data1D *imgdest, FLGR_Data1D *imgMarker, FLGR_Data1D *imgMask, FLGR_Data1D *nhb) {
  FLGR_MACRO_GEODESIC_ERODE_1D(fgINT8);
}
void flgr1d_geodesic_erode_fgINT16(FLGR_Data1D *imgdest, FLGR_Data1D *imgMarker, FLGR_Data1D *imgMask, FLGR_Data1D *nhb) {
  FLGR_MACRO_GEODESIC_ERODE_1D(fgINT16);
}
void flgr1d_geodesic_erode_fgINT32(FLGR_Data1D *imgdest, FLGR_Data1D *imgMarker, FLGR_Data1D *imgMask, FLGR_Data1D *nhb) {
  FLGR_MACRO_GEODESIC_ERODE_1D(fgINT32);
}
void flgr1d_geodesic_erode_fgFLOAT32(FLGR_Data1D *imgdest, FLGR_Data1D *imgMarker, FLGR_Data1D *imgMask, FLGR_Data1D *nhb) {
  FLGR_MACRO_GEODESIC_ERODE_1D(fgFLOAT32);
}
void flgr1d_geodesic_erode_fgFLOAT64(FLGR_Data1D *imgdest, FLGR_Data1D *imgMarker, FLGR_Data1D *imgMask, FLGR_Data1D *nhb) {
  FLGR_MACRO_GEODESIC_ERODE_1D(fgFLOAT64);
}
////////////////////////////////////////////////////////////////////////////
/*! Compute Geodesic Dilation
 *  @param imgdest : image output
 *  @param imgMarker : marker image input
 *  @param imgMask : mask image input
 *  @param nhb : neighborhood definition
 *  @returns FLGR_RET_OK, ...
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr1d_geodesic_erode(FLGR_Data1D *imgdest, FLGR_Data1D *imgMarker, FLGR_Data1D *imgMask, FLGR_Data1D *nhb) {

  FLGR_DECLARE_FUNCTION;

  if((imgdest==NULL) || (imgMarker==NULL) || (imgMask==NULL) || (nhb==NULL)){
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  FLGR_DISPATCH_PROCEDURE(imgdest->type,flgr1d_geodesic_erode,imgdest,imgMarker,imgMask,nhb);
}








/***************************************************************************************************/
/***************************************************************************************************/
/************************************************ 2D ***********************************************/
/***************************************************************************************************/
/***************************************************************************************************/

















////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
#define FLGR_MACRO_GEODESIC_DILATE_2D(dtype)		\
  flgr2d_dilate_##dtype(imgdest,imgMarker,nhb);		\
  flgr2d_arith_inf_##dtype(imgdest,imgMask,imgdest)

void flgr2d_geodesic_dilate_fgBIT(FLGR_Data2D *imgdest, FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask, FLGR_Data2D *nhb) {
  FLGR_MACRO_GEODESIC_DILATE_2D(fgBIT);
}
void flgr2d_geodesic_dilate_fgUINT8(FLGR_Data2D *imgdest, FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask, FLGR_Data2D *nhb) {
  FLGR_MACRO_GEODESIC_DILATE_2D(fgUINT8);
}
void flgr2d_geodesic_dilate_fgUINT16(FLGR_Data2D *imgdest, FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask, FLGR_Data2D *nhb) {
  FLGR_MACRO_GEODESIC_DILATE_2D(fgUINT16);
}
void flgr2d_geodesic_dilate_fgUINT32(FLGR_Data2D *imgdest, FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask, FLGR_Data2D *nhb) {
  FLGR_MACRO_GEODESIC_DILATE_2D(fgUINT32);
}
void flgr2d_geodesic_dilate_fgINT8(FLGR_Data2D *imgdest, FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask, FLGR_Data2D *nhb) {
  FLGR_MACRO_GEODESIC_DILATE_2D(fgINT8);
}
void flgr2d_geodesic_dilate_fgINT16(FLGR_Data2D *imgdest, FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask, FLGR_Data2D *nhb) {
  FLGR_MACRO_GEODESIC_DILATE_2D(fgINT16);
}
void flgr2d_geodesic_dilate_fgINT32(FLGR_Data2D *imgdest, FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask, FLGR_Data2D *nhb) {
  FLGR_MACRO_GEODESIC_DILATE_2D(fgINT32);
}
void flgr2d_geodesic_dilate_fgFLOAT32(FLGR_Data2D *imgdest, FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask, FLGR_Data2D *nhb) {
  FLGR_MACRO_GEODESIC_DILATE_2D(fgFLOAT32);
}
void flgr2d_geodesic_dilate_fgFLOAT64(FLGR_Data2D *imgdest, FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask, FLGR_Data2D *nhb) {
  FLGR_MACRO_GEODESIC_DILATE_2D(fgFLOAT64);
}
////////////////////////////////////////////////////////////////////////////
/*! Compute Geodesic Dilation
 *  @param imgdest : image output
 *  @param imgMarker : marker image input
 *  @param imgMask : mask image input
 *  @param nhb : neighborhood definition
 *  @returns FLGR_RET_OK, ...
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr2d_geodesic_dilate(FLGR_Data2D *imgdest, FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask, FLGR_Data2D *nhb) {

  FLGR_DECLARE_FUNCTION;

  if((imgdest==NULL) || (imgMarker==NULL) || (imgMask==NULL) || (nhb==NULL)){
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  FLGR_DISPATCH_PROCEDURE(imgdest->type,flgr2d_geodesic_dilate,imgdest,imgMarker,imgMask,nhb);
}

////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
#define FLGR_MACRO_GEODESIC_ERODE_2D(dtype)		\
  flgr2d_erode_##dtype(imgdest,imgMarker,nhb);		\
  flgr2d_arith_sup_##dtype(imgdest,imgMask,imgdest)

void flgr2d_geodesic_erode_fgBIT(FLGR_Data2D *imgdest, FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask, FLGR_Data2D *nhb) {
  FLGR_MACRO_GEODESIC_ERODE_2D(fgBIT);
}
void flgr2d_geodesic_erode_fgUINT8(FLGR_Data2D *imgdest, FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask, FLGR_Data2D *nhb) {
  FLGR_MACRO_GEODESIC_ERODE_2D(fgUINT8);
}
void flgr2d_geodesic_erode_fgUINT16(FLGR_Data2D *imgdest, FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask, FLGR_Data2D *nhb) {
  FLGR_MACRO_GEODESIC_ERODE_2D(fgUINT16);
}
void flgr2d_geodesic_erode_fgUINT32(FLGR_Data2D *imgdest, FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask, FLGR_Data2D *nhb) {
  FLGR_MACRO_GEODESIC_ERODE_2D(fgUINT32);
}
void flgr2d_geodesic_erode_fgINT8(FLGR_Data2D *imgdest, FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask, FLGR_Data2D *nhb) {
  FLGR_MACRO_GEODESIC_ERODE_2D(fgINT8);
}
void flgr2d_geodesic_erode_fgINT16(FLGR_Data2D *imgdest, FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask, FLGR_Data2D *nhb) {
  FLGR_MACRO_GEODESIC_ERODE_2D(fgINT16);
}
void flgr2d_geodesic_erode_fgINT32(FLGR_Data2D *imgdest, FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask, FLGR_Data2D *nhb) {
  FLGR_MACRO_GEODESIC_ERODE_2D(fgINT32);
}
void flgr2d_geodesic_erode_fgFLOAT32(FLGR_Data2D *imgdest, FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask, FLGR_Data2D *nhb) {
  FLGR_MACRO_GEODESIC_ERODE_2D(fgFLOAT32);
}
void flgr2d_geodesic_erode_fgFLOAT64(FLGR_Data2D *imgdest, FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask, FLGR_Data2D *nhb) {
  FLGR_MACRO_GEODESIC_ERODE_2D(fgFLOAT64);
}
////////////////////////////////////////////////////////////////////////////
/*! Compute Geodesic Dilation
 *  @param imgdest : image output
 *  @param imgMarker : marker image input
 *  @param imgMask : mask image input
 *  @param nhb : neighborhood definition
 *  @returns FLGR_RET_OK, ...
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr2d_geodesic_erode(FLGR_Data2D *imgdest, FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask, FLGR_Data2D *nhb) {
  FLGR_DECLARE_FUNCTION;

  if((imgdest==NULL) || (imgMarker==NULL) || (imgMask==NULL) || (nhb==NULL)){
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  FLGR_DISPATCH_PROCEDURE(imgdest->type,flgr2d_geodesic_erode,imgdest,imgMarker,imgMask,nhb);
}





////////////////////////////////////////////////////////////////////////////
// Macro for different type of flgr_georec_dil_back_push_fifo
////////////////////////////////////////////////////////////////////////////
#define Georec_dil_back_push_fifo(dtype)		\
  dtype *pextrMarker;					\
  dtype *pextrMask;					\
  int *list_coord_x, *list_coord_y;			\
  int u,v,i,j,k,l,m,h2,w2;				\
							\
  i=extrMarker->center_coord_y;				\
  j=extrMarker->center_coord_x;				\
							\
  pextrMarker=(dtype *) extrMarker->list_data_val[0];	\
  pextrMask=(dtype *) extrMask->list_data_val[0];	\
  list_coord_x = extrMarker->list_coord_x[0];		\
  list_coord_y = extrMarker->list_coord_y[0];		\
							\
  h2 = extrMarker->nhb_size_y/2;			\
  w2 = extrMarker->nhb_size_x/2;			\
							\
  for(m=0 ; m<extrMarker->size[0] ; m++) {		\
    u=list_coord_y[m];					\
    v=list_coord_x[m];					\
    k=i+u-h2;						\
    l=j+v-w2;						\
							\
    if( (pextrMarker[m] < pixCenter) &&			\
	(pextrMarker[m] < pextrMask[m]) ) {		\
      flgr_static_fifo_write(fifo,k,l);			\
    }							\
							\
  }							\
  return




void flgr_georec_dil_back_push_fifo_fgUINT8(FLGR_StaticFifo *fifo, FLGR_NhbBox2D *extrMarker,
					    FLGR_NhbBox2D *extrMask, fgUINT8 pixCenter) {
  Georec_dil_back_push_fifo(fgUINT8);
}

void flgr_georec_dil_back_push_fifo_fgUINT16(FLGR_StaticFifo *fifo,  FLGR_NhbBox2D *extrMarker,
					     FLGR_NhbBox2D *extrMask, fgUINT16 pixCenter) {
  Georec_dil_back_push_fifo(fgUINT16);
}

void flgr_georec_dil_back_push_fifo_fgUINT32(FLGR_StaticFifo *fifo, FLGR_NhbBox2D *extrMarker,
					     FLGR_NhbBox2D *extrMask, fgUINT32 pixCenter) {
  Georec_dil_back_push_fifo(fgUINT32);
}

void flgr_georec_dil_back_push_fifo_fgINT8(FLGR_StaticFifo *fifo,  FLGR_NhbBox2D *extrMarker,
					   FLGR_NhbBox2D *extrMask, fgINT8 pixCenter) {
  Georec_dil_back_push_fifo(fgINT8);
}

void flgr_georec_dil_back_push_fifo_fgINT16(FLGR_StaticFifo *fifo, FLGR_NhbBox2D *extrMarker,
					    FLGR_NhbBox2D *extrMask, fgINT16 pixCenter) {
  Georec_dil_back_push_fifo(fgINT16);
}

void flgr_georec_dil_back_push_fifo_fgINT32(FLGR_StaticFifo *fifo, FLGR_NhbBox2D *extrMarker,
					    FLGR_NhbBox2D *extrMask, fgINT32 pixCenter) {
  Georec_dil_back_push_fifo(fgINT32);
}

void flgr_georec_dil_back_push_fifo_fgFLOAT32(FLGR_StaticFifo *fifo, FLGR_NhbBox2D *extrMarker,
					      FLGR_NhbBox2D *extrMask, fgFLOAT32 pixCenter) {
  Georec_dil_back_push_fifo(fgFLOAT32);
}

void flgr_georec_dil_back_push_fifo_fgFLOAT64(FLGR_StaticFifo *fifo, FLGR_NhbBox2D *extrMarker,
					      FLGR_NhbBox2D *extrMask, fgFLOAT64 pixCenter) {
  Georec_dil_back_push_fifo(fgFLOAT64);
}

////////////////////////////////////////////////////////////////////////////
// Macro for different type of flgr_georec_dil_back_push_fifo
////////////////////////////////////////////////////////////////////////////
#define Georec_ero_back_push_fifo(dtype)		\
  dtype *pextrMarker;					\
  dtype *pextrMask;					\
  int *list_coord_x, *list_coord_y;			\
  int u,v,i,j,k,l,m,h2,w2;				\
							\
  i=extrMarker->center_coord_y;				\
  j=extrMarker->center_coord_x;				\
							\
  pextrMarker=(dtype *) extrMarker->list_data_val[0];	\
  pextrMask=(dtype *) extrMask->list_data_val[0];	\
  list_coord_x = extrMarker->list_coord_x[0];		\
  list_coord_y = extrMarker->list_coord_y[0];		\
							\
  h2 = extrMarker->nhb_size_y/2;			\
  w2 = extrMarker->nhb_size_x/2;			\
							\
  for(m=0 ; m<extrMarker->size[0] ; m++) {		\
    u=list_coord_y[m];					\
    v=list_coord_x[m];					\
    k=i+u-h2;						\
    l=j+v-w2;						\
							\
    if( (pextrMarker[m] > pixCenter) &&			\
	(pextrMarker[m] > pextrMask[m]) ) {		\
      flgr_static_fifo_write(fifo,k,l);			\
    }							\
							\
  }							\
  return

/* //////////////////////////////////////////////////////////////////////////// */
/* // Macro for different type of flgr_georec_ero_back_push_fifo */
/* //////////////////////////////////////////////////////////////////////////// */
/* #define Georec_ero_back_push_fifo(dtype)	\ */
/*   dtype *pextrMarker;				\ */
/*   dtype *pextrMask;				\ */
/*   int u,v,i,j,k,l,m,h2,w2;			\ */
/* 						\ */
/*   i=extrMarker->centerY;			\ */
/*   j=extrMarker->centerX;			\ */
/* 						\ */
/*   pextrMarker=(dtype *) extrMarker->listValue;	\ */
/*   pextrMask=(dtype *) extrMask->listValue;	\ */
/* 						\ */
/*   h2 = extrMarker->size_y/2;			\ */
/*   w2 = extrMarker->size_x/2;			\ */
/* 						\ */
/*   for(m=0 ; m<extrMarker->size ; m++) {		\ */
/*     u=extrMarker->listY[m];			\ */
/*     v=extrMarker->listX[m];			\ */
/*     k=i+u-h2;					\ */
/*     l=j+v-w2;					\ */
/*    						\ */
/*     if( (pextrMarker[m] > pixCenter) &&		\ */
/* 	(pextrMarker[m] > pextrMask[m]) ) {	\ */
/*       flgr_static_fifo_write(fifo,k,l);		\ */
/*     }						\ */
/* 						\ */
/*   }						\ */
/*   return */


void flgr_georec_ero_back_push_fifo_fgUINT8(FLGR_StaticFifo *fifo, FLGR_NhbBox2D *extrMarker,
					    FLGR_NhbBox2D *extrMask, fgUINT8 pixCenter) {
  Georec_ero_back_push_fifo(fgUINT8);
}


void flgr_georec_ero_back_push_fifo_fgUINT16(FLGR_StaticFifo *fifo, FLGR_NhbBox2D *extrMarker,
					     FLGR_NhbBox2D *extrMask, fgUINT16 pixCenter) {
  Georec_ero_back_push_fifo(fgUINT16);
}


void flgr_georec_ero_back_push_fifo_fgUINT32(FLGR_StaticFifo *fifo, FLGR_NhbBox2D *extrMarker,
					     FLGR_NhbBox2D *extrMask, fgUINT32 pixCenter) {
  Georec_ero_back_push_fifo(fgUINT32);
}


void flgr_georec_ero_back_push_fifo_fgINT8(FLGR_StaticFifo *fifo, FLGR_NhbBox2D *extrMarker,
					   FLGR_NhbBox2D *extrMask, fgINT8 pixCenter) {
  Georec_ero_back_push_fifo(fgINT8);
}


void flgr_georec_ero_back_push_fifo_fgINT16(FLGR_StaticFifo *fifo, FLGR_NhbBox2D *extrMarker,
					    FLGR_NhbBox2D *extrMask, fgINT16 pixCenter) {
  Georec_ero_back_push_fifo(fgINT16);
}


void flgr_georec_ero_back_push_fifo_fgINT32(FLGR_StaticFifo *fifo, FLGR_NhbBox2D *extrMarker,
					    FLGR_NhbBox2D *extrMask, fgINT32 pixCenter) {
  Georec_ero_back_push_fifo(fgINT32);
}


void flgr_georec_ero_back_push_fifo_fgFLOAT32(FLGR_StaticFifo *fifo, FLGR_NhbBox2D *extrMarker,
					      FLGR_NhbBox2D *extrMask, fgFLOAT32 pixCenter) {
  Georec_ero_back_push_fifo(fgFLOAT32);
}


void flgr_georec_ero_back_push_fifo_fgFLOAT64(FLGR_StaticFifo *fifo, FLGR_NhbBox2D *extrMarker,
					      FLGR_NhbBox2D *extrMask, fgFLOAT64 pixCenter) {
  Georec_ero_back_push_fifo(fgFLOAT64);
}








////////////////////////////////////////////////////////////////////////////
// Macro for different type of
////////////////////////////////////////////////////////////////////////////
#define AntirasterSlideRecWindowFifo(dtype, fifoop, arithop, nhbop)	\
  int i,j;								\
  dtype pixval;								\
  FLGR_Vector *result,*vec_arith;					\
  FLGR_Data2D *nhbars;							\
  FLGR_Data2D *nhbEven,*nhbOdd;						\
  FLGR_NhbBox2D *maskextr,*extr;					\
									\
  result = flgr_vector_create(imgMarker->spp,imgMarker->type);		\
  vec_arith = flgr_vector_create(imgMarker->spp,imgMarker->type);	\
									\
  extr = flgr2d_create_neighbor_box(nhb);				\
  maskextr = flgr2d_create_neighbor_box(nhb);				\
									\
  nhbEven=flgr2d_create_neighborhood_from(nhb);				\
  nhbOdd=flgr2d_create_neighborhood_from(nhb);				\
									\
  flgr2d_fill_nhbs_for_6_connexity(nhbEven,nhbOdd,nhb,FLGR_NHB_NO_SYM);	\
									\
  flgr2d_apply_anti_raster_scan_method_##dtype(nhbOdd);			\
  flgr2d_apply_anti_raster_scan_method_##dtype(nhbEven);		\
									\
  for(i=imgMarker->size_y-1 ; i>=0 ; i--) {				\
									\
    for(j=imgMarker->size_x-1 ; j>=0 ; j--) {				\
									\
      nhbars = (((i%2)==1) ? nhbOdd : nhbEven);				\
									\
      flgr2d_get_neighborhood_##dtype(extr,imgMarker,			\
				      nhbars, i, j);			\
      flgr2d_get_neighborhood_##dtype(maskextr,imgMask,			\
				      nhbars, i, j);			\
									\
      nhbop(result,extr);						\
      									\
      flgr2d_get_data_vector_no_norm_##dtype(imgMask,i,j,vec_arith);	\
      									\
      arithop(result,result,vec_arith);					\
 									\
      flgr2d_set_data_vector_##dtype(imgMarker,i,j,result);		\
									\
      flgr_vector_get_element_##dtype(result, 0, &pixval);		\
      									\
      fifoop(fifo,extr,maskextr,pixval);				\
									\
    }									\
  }									\
									\
  flgr2d_destroy(nhbOdd);						\
  flgr2d_destroy(nhbEven);						\
									\
  flgr2d_destroy_neighbor_box(extr);					\
  flgr2d_destroy_neighbor_box(maskextr);				\
  flgr_vector_destroy(vec_arith);					\
  flgr_vector_destroy(result);						\
  									\
  return



void flgr_anti_raster_slide_recursive_dil_fifo_fgUINT8(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
						       FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {
  AntirasterSlideRecWindowFifo(fgUINT8,
			       flgr_georec_dil_back_push_fifo_fgUINT8,
			       flgr_vector_inf_fgUINT8,
			       flgr2d_get_nhb_maximum_fgUINT8);
}

void flgr_anti_raster_slide_recursive_dil_fifo_fgUINT16(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
							FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {

  AntirasterSlideRecWindowFifo(fgUINT16,
			       flgr_georec_dil_back_push_fifo_fgUINT16,
			       flgr_vector_inf_fgUINT16,
			       flgr2d_get_nhb_maximum_fgUINT16);
}

void flgr_anti_raster_slide_recursive_dil_fifo_fgUINT32(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
							FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {


  AntirasterSlideRecWindowFifo(fgUINT32,
			       flgr_georec_dil_back_push_fifo_fgUINT32,
			       flgr_vector_inf_fgUINT32,
			       flgr2d_get_nhb_maximum_fgUINT32);
}

void flgr_anti_raster_slide_recursive_dil_fifo_fgINT8(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
						      FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {


  AntirasterSlideRecWindowFifo(fgINT8,
			       flgr_georec_dil_back_push_fifo_fgINT8,
			       flgr_vector_inf_fgINT8,
			       flgr2d_get_nhb_maximum_fgINT8);
}

void flgr_anti_raster_slide_recursive_dil_fifo_fgINT16(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
						       FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {


  AntirasterSlideRecWindowFifo(fgINT16,
			       flgr_georec_dil_back_push_fifo_fgINT16,
			       flgr_vector_inf_fgINT16,
			       flgr2d_get_nhb_maximum_fgINT16);
}

void flgr_anti_raster_slide_recursive_dil_fifo_fgINT32(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
						       FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {


  AntirasterSlideRecWindowFifo(fgINT32,
			       flgr_georec_dil_back_push_fifo_fgINT32,
			       flgr_vector_inf_fgINT32,
			       flgr2d_get_nhb_maximum_fgINT32);
}

void flgr_anti_raster_slide_recursive_dil_fifo_fgFLOAT32(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
							 FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {

  AntirasterSlideRecWindowFifo(fgFLOAT32,
			       flgr_georec_dil_back_push_fifo_fgFLOAT32,
			       flgr_vector_inf_fgFLOAT32,
			       flgr2d_get_nhb_maximum_fgFLOAT32);
}

void flgr_anti_raster_slide_recursive_dil_fifo_fgFLOAT64(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
							 FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {

  AntirasterSlideRecWindowFifo(fgFLOAT64,
			       flgr_georec_dil_back_push_fifo_fgFLOAT64,
			       flgr_vector_inf_fgFLOAT64,
			       flgr2d_get_nhb_maximum_fgFLOAT64);
}






void flgr_anti_raster_slide_recursive_ero_fifo_fgUINT8(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
						       FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {
  AntirasterSlideRecWindowFifo(fgUINT8,
			       flgr_georec_ero_back_push_fifo_fgUINT8,
			       flgr_vector_sup_fgUINT8,
			       flgr2d_get_nhb_minimum_fgUINT8);
}

void flgr_anti_raster_slide_recursive_ero_fifo_fgUINT16(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
							FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {

  AntirasterSlideRecWindowFifo(fgUINT16,
			       flgr_georec_ero_back_push_fifo_fgUINT16,
			       flgr_vector_sup_fgUINT16,
			       flgr2d_get_nhb_minimum_fgUINT16);
}

void flgr_anti_raster_slide_recursive_ero_fifo_fgUINT32(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
							FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {


  AntirasterSlideRecWindowFifo(fgUINT32,
			       flgr_georec_ero_back_push_fifo_fgUINT32,
			       flgr_vector_sup_fgUINT32,
			       flgr2d_get_nhb_minimum_fgUINT32);
}

void flgr_anti_raster_slide_recursive_ero_fifo_fgINT8(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
						      FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {


  AntirasterSlideRecWindowFifo(fgINT8,
			       flgr_georec_ero_back_push_fifo_fgINT8,
			       flgr_vector_sup_fgINT8,
			       flgr2d_get_nhb_minimum_fgINT8);
}

void flgr_anti_raster_slide_recursive_ero_fifo_fgINT16(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
						       FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {


  AntirasterSlideRecWindowFifo(fgINT16,
			       flgr_georec_ero_back_push_fifo_fgINT16,
			       flgr_vector_sup_fgINT16,
			       flgr2d_get_nhb_minimum_fgINT16);
}

void flgr_anti_raster_slide_recursive_ero_fifo_fgINT32(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
						       FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {


  AntirasterSlideRecWindowFifo(fgINT32,
			       flgr_georec_ero_back_push_fifo_fgINT32,
			       flgr_vector_sup_fgINT32,
			       flgr2d_get_nhb_minimum_fgINT32);
}

void flgr_anti_raster_slide_recursive_ero_fifo_fgFLOAT32(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
							 FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {

  AntirasterSlideRecWindowFifo(fgFLOAT32,
			       flgr_georec_ero_back_push_fifo_fgFLOAT32,
			       flgr_vector_sup_fgFLOAT32,
			       flgr2d_get_nhb_minimum_fgFLOAT32);
}

void flgr_anti_raster_slide_recursive_ero_fifo_fgFLOAT64(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
							 FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {

  AntirasterSlideRecWindowFifo(fgFLOAT64,
			       flgr_georec_ero_back_push_fifo_fgFLOAT64,
			       flgr_vector_sup_fgFLOAT64,
			       flgr2d_get_nhb_minimum_fgFLOAT64);
}



////////////////////////////////////////////////////////////////////////////
// Different type of flgr_georec_dil_push_fifo
////////////////////////////////////////////////////////////////////////////
#define Georec_Dil_Push_Fifo(dtype)					\
  dtype *pextrMarker;							\
  dtype *pextrMask;							\
  int *list_x, *list_y;							\
  int u,v,i,j,k,l,m,w2,h2;						\
  dtype pixCenter;							\
  dtype mini;								\
									\
  i=extrmarker->center_coord_y;						\
  j=extrmarker->center_coord_x;						\
									\
  pextrMarker=(dtype *) extrmarker->list_data_val[0];			\
  pextrMask=(dtype *) extrmask->list_data_val[0];			\
  list_x = (int *) extrmarker->list_coord_x[0];				\
  list_y = (int *) extrmarker->list_coord_y[0];				\
									\
  flgr_vector_get_element(extrmarker->center_data_val,0,&pixCenter);	\
									\
  w2 = extrmarker->nhb_size_x/2;					\
  h2 = extrmarker->nhb_size_y/2;					\
									\
  for(m=0 ; m<extrmarker->size[0] ; m++) {				\
    u=list_y[m];							\
    v=list_x[m];							\
    k=i+u-h2;								\
    l=j+v-w2;								\
									\
    if( (pextrMarker[m] < pixCenter) &&					\
	(pextrMarker[m] < pextrMask[m]) ) {				\
      mini=FLGR_MIN(pixCenter,pextrMask[m]);				\
      flgr2d_set_data_array_##dtype((dtype **)imgMarker->array,k,l,mini); \
      flgr_static_fifo_write(fifo,k,l);					\
    }									\
  }									\
  return


void flgr_georec_dil_push_fifo_fgUINT8(FLGR_StaticFifo *fifo,
				       FLGR_NhbBox2D *extrmarker,
				       FLGR_NhbBox2D *extrmask, FLGR_Data2D *imgMarker) {


  Georec_Dil_Push_Fifo(fgUINT8);

}

void flgr_georec_dil_push_fifo_fgUINT16(FLGR_StaticFifo *fifo,
					FLGR_NhbBox2D *extrmarker,
					FLGR_NhbBox2D *extrmask, FLGR_Data2D *imgMarker) {

  Georec_Dil_Push_Fifo(fgUINT16);
}

void flgr_georec_dil_push_fifo_fgUINT32(FLGR_StaticFifo *fifo,
					FLGR_NhbBox2D *extrmarker,
					FLGR_NhbBox2D *extrmask, FLGR_Data2D *imgMarker) {

  Georec_Dil_Push_Fifo(fgUINT32);
}

void flgr_georec_dil_push_fifo_fgINT8(FLGR_StaticFifo *fifo,
				      FLGR_NhbBox2D *extrmarker,
				      FLGR_NhbBox2D *extrmask, FLGR_Data2D *imgMarker) {

  Georec_Dil_Push_Fifo(fgINT8);
}

void flgr_georec_dil_push_fifo_fgINT16(FLGR_StaticFifo *fifo,
				       FLGR_NhbBox2D *extrmarker,
				       FLGR_NhbBox2D *extrmask, FLGR_Data2D *imgMarker) {


  Georec_Dil_Push_Fifo(fgINT16);
}

void flgr_georec_dil_push_fifo_fgINT32(FLGR_StaticFifo *fifo,
				       FLGR_NhbBox2D *extrmarker,
				       FLGR_NhbBox2D *extrmask, FLGR_Data2D *imgMarker) {

  Georec_Dil_Push_Fifo(fgINT32);
}

void flgr_georec_dil_push_fifo_fgFLOAT32(FLGR_StaticFifo *fifo,
					 FLGR_NhbBox2D *extrmarker,
					 FLGR_NhbBox2D *extrmask, FLGR_Data2D *imgMarker) {

  Georec_Dil_Push_Fifo(fgFLOAT32);
}

void flgr_georec_dil_push_fifo_fgFLOAT64(FLGR_StaticFifo *fifo,
					 FLGR_NhbBox2D *extrmarker,
					 FLGR_NhbBox2D *extrmask, FLGR_Data2D *imgMarker) {

  Georec_Dil_Push_Fifo(fgFLOAT64);
}



////////////////////////////////////////////////////////////////////////////
// Different type of flgr_georec_dil_push_fifo
////////////////////////////////////////////////////////////////////////////
#define Georec_Ero_Push_Fifo(dtype)					\
  dtype *pextrMarker;							\
  dtype *pextrMask;							\
  int *list_x, *list_y;							\
  int u,v,i,j,k,l,m,w2,h2;						\
  dtype pixCenter;							\
  dtype maxi;								\
									\
  i=extrmarker->center_coord_y;						\
  j=extrmarker->center_coord_x;						\
									\
  pextrMarker=(dtype *) extrmarker->list_data_val[0];			\
  pextrMask=(dtype *) extrmask->list_data_val[0];			\
  list_x = (int *) extrmarker->list_coord_x[0];				\
  list_y = (int *) extrmarker->list_coord_y[0];				\
									\
  flgr_vector_get_element(extrmarker->center_data_val,0,&pixCenter);	\
									\
  w2 = extrmarker->nhb_size_x/2;					\
  h2 = extrmarker->nhb_size_y/2;					\
									\
  for(m=0 ; m<extrmarker->size[0] ; m++) {				\
    u=list_y[m];							\
    v=list_x[m];							\
    k=i+u-h2;								\
    l=j+v-w2;								\
									\
    if( (pextrMarker[m] > pixCenter) &&					\
	(pextrMarker[m] > pextrMask[m]) ) {				\
      maxi=FLGR_MAX(pixCenter,pextrMask[m]);				\
      flgr2d_set_data_array_##dtype((dtype **)imgMarker->array,k,l,maxi); \
      flgr_static_fifo_write(fifo,k,l);					\
    }									\
  }									\
  return


void flgr_georec_ero_push_fifo_fgUINT8(FLGR_StaticFifo *fifo,
				       FLGR_NhbBox2D *extrmarker,
				       FLGR_NhbBox2D *extrmask, FLGR_Data2D *imgMarker) {

  Georec_Ero_Push_Fifo(fgUINT8);

}

void flgr_georec_ero_push_fifo_fgUINT16(FLGR_StaticFifo *fifo,
					FLGR_NhbBox2D *extrmarker,
					FLGR_NhbBox2D *extrmask, FLGR_Data2D *imgMarker) {

  Georec_Ero_Push_Fifo(fgUINT16);
}

void flgr_georec_ero_push_fifo_fgUINT32(FLGR_StaticFifo *fifo,
					FLGR_NhbBox2D *extrmarker,
					FLGR_NhbBox2D *extrmask, FLGR_Data2D *imgMarker) {

  Georec_Ero_Push_Fifo(fgUINT32);
}

void flgr_georec_ero_push_fifo_fgINT8(FLGR_StaticFifo *fifo,
				      FLGR_NhbBox2D *extrmarker,
				      FLGR_NhbBox2D *extrmask, FLGR_Data2D *imgMarker) {

  Georec_Ero_Push_Fifo(fgINT8);
}

void flgr_georec_ero_push_fifo_fgINT16(FLGR_StaticFifo *fifo,
				       FLGR_NhbBox2D *extrmarker,
				       FLGR_NhbBox2D *extrmask, FLGR_Data2D *imgMarker) {

  Georec_Ero_Push_Fifo(fgINT16);
}

void flgr_georec_ero_push_fifo_fgINT32(FLGR_StaticFifo *fifo,
				       FLGR_NhbBox2D *extrmarker,
				       FLGR_NhbBox2D *extrmask, FLGR_Data2D *imgMarker) {

  Georec_Ero_Push_Fifo(fgINT32);
}

void flgr_georec_ero_push_fifo_fgFLOAT32(FLGR_StaticFifo *fifo,
					 FLGR_NhbBox2D *extrmarker,
					 FLGR_NhbBox2D *extrmask, FLGR_Data2D *imgMarker) {

  Georec_Ero_Push_Fifo(fgFLOAT32);
}

void flgr_georec_ero_push_fifo_fgFLOAT64(FLGR_StaticFifo *fifo,
					 FLGR_NhbBox2D *extrmarker,
					 FLGR_NhbBox2D *extrmask, FLGR_Data2D *imgMarker) {

  Georec_Ero_Push_Fifo(fgFLOAT64);
}



////////////////////////////////////////////////////////////////////////////
// Macro for different type of flgr_propag_fifo_content (dtype)
////////////////////////////////////////////////////////////////////////////
#define Georec_propag_fifo_cont(dtype,fifoop)				\
  int row,col;								\
  FLGR_Data2D *nhbOdd,*nhbEven, *pnhb;					\
  FLGR_NhbBox2D *maskextr,*extr;					\
									\
  extr = flgr2d_create_neighbor_box(nhb);				\
  maskextr = flgr2d_create_neighbor_box(nhb);				\
									\
  nhbOdd = flgr2d_create_neighborhood_from(nhb);			\
  nhbEven = flgr2d_create_neighborhood_from(nhb);			\
									\
  flgr2d_fill_nhbs_for_6_connexity(nhbEven,nhbOdd,nhb,FLGR_NHB_NO_SYM);	\
									\
  while(!flgr_static_fifo_is_empty(fifo)) {					\
    flgr_static_fifo_read(fifo,&row,&col);					\
    pnhb = (((row%2)==1) ? nhbOdd : nhbEven);				\
    									\
    flgr2d_get_neighborhood_##dtype(extr,imgMarker,			\
				    pnhb, row, col);			\
    flgr2d_get_neighborhood_##dtype(maskextr,imgMask,			\
				    pnhb, row, col);			\
    fifoop(fifo, extr, maskextr, imgMarker);				\
									\
  }									\
  									\
  flgr2d_destroy(nhbOdd);						\
  flgr2d_destroy(nhbEven);						\
									\
  flgr2d_destroy_neighbor_box(extr);					\
  flgr2d_destroy_neighbor_box(maskextr);				\
  return


void flgr_georec_ero_propag_fifo_fgUINT8(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
					 FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {
  Georec_propag_fifo_cont(fgUINT8,flgr_georec_ero_push_fifo_fgUINT8);
}

void flgr_georec_ero_propag_fifo_fgUINT16(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
					  FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {
  Georec_propag_fifo_cont(fgUINT16,flgr_georec_ero_push_fifo_fgUINT16);
}


void flgr_georec_ero_propag_fifo_fgUINT32(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
					  FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {
  Georec_propag_fifo_cont(fgUINT32,flgr_georec_ero_push_fifo_fgUINT32);
}

void flgr_georec_ero_propag_fifo_fgINT8(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
					FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {
  Georec_propag_fifo_cont(fgINT8,flgr_georec_ero_push_fifo_fgINT8);
}

void flgr_georec_ero_propag_fifo_fgINT16(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
					 FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {
  Georec_propag_fifo_cont(fgINT16,flgr_georec_ero_push_fifo_fgINT16);

}

void flgr_georec_ero_propag_fifo_fgINT32(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
					 FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {
  Georec_propag_fifo_cont(fgINT32,flgr_georec_ero_push_fifo_fgINT32);

}

void flgr_georec_ero_propag_fifo_fgFLOAT32(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
					   FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {
  Georec_propag_fifo_cont(fgFLOAT32,flgr_georec_ero_push_fifo_fgFLOAT32);

}

void flgr_georec_ero_propag_fifo_fgFLOAT64(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
					   FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {
  Georec_propag_fifo_cont(fgFLOAT64,flgr_georec_ero_push_fifo_fgFLOAT64);

}




void flgr_georec_dil_propag_fifo_fgUINT8(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
					 FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {
  Georec_propag_fifo_cont(fgUINT8,flgr_georec_dil_push_fifo_fgUINT8);
}

void flgr_georec_dil_propag_fifo_fgUINT16(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
					  FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {
  Georec_propag_fifo_cont(fgUINT16,flgr_georec_dil_push_fifo_fgUINT16);
}


void flgr_georec_dil_propag_fifo_fgUINT32(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
					  FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {
  Georec_propag_fifo_cont(fgUINT32,flgr_georec_dil_push_fifo_fgUINT32);
}

void flgr_georec_dil_propag_fifo_fgINT8(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
					FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {
  Georec_propag_fifo_cont(fgINT8,flgr_georec_dil_push_fifo_fgINT8);
}

void flgr_georec_dil_propag_fifo_fgINT16(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
					 FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {
  Georec_propag_fifo_cont(fgINT16,flgr_georec_dil_push_fifo_fgINT16);

}

void flgr_georec_dil_propag_fifo_fgINT32(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
					 FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {
  Georec_propag_fifo_cont(fgINT32,flgr_georec_dil_push_fifo_fgINT32);

}

void flgr_georec_dil_propag_fifo_fgFLOAT32(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
					   FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {
  Georec_propag_fifo_cont(fgFLOAT32,flgr_georec_dil_push_fifo_fgFLOAT32);

}

void flgr_georec_dil_propag_fifo_fgFLOAT64(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
					   FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {
  Georec_propag_fifo_cont(fgFLOAT64,flgr_georec_dil_push_fifo_fgFLOAT64);

}


////////////////////////////////////////////////////////////////////////////
// Macro for different type of flgr2d_geodesic_Reconstruction
////////////////////////////////////////////////////////////////////////////
#define GeodesicReconstruction(dtype,dtypename,nhbop,arithop,		\
			       backfifoop,propagfifoop)			\
									\
  FLGR_Data2D *nhb;							\
  FLGR_StaticFifo *fifo;							\
  FLGR_DECLARE_FUNCTION;						\
									\
  nhb = flgr2d_create_neighborhood_from_connexity(imgMarker->spp,dtypename,connexity); \
									\
  if(nhb==NULL) return FLGR_RET_ALLOCATION_ERROR;			\
									\
  fifo = flgr_static_fifo_init(imgMarker->size_y,imgMarker->size_x);		\
  flgr2d_raster_slide_window_before_op_##dtype(imgMarker,		\
					       imgMarker,imgMask,nhb,FLGR_NHB_NO_SYM, \
					       nhbop,arithop);		\
									\
  backfifoop(imgMarker,imgMask,nhb,fifo);				\
  propagfifoop(imgMarker,imgMask,nhb,fifo);				\
									\
  flgr2d_destroy(nhb);							\
  flgr_static_fifo_destroy(fifo);						\
									\
  return FLGR_RET_OK




FLGR_Ret flgr2d_geodesic_reconstruct_dilate_fgBIT(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask, FLGR_Connexity connexity) {
  flgr_no_define_type_function(FLGR_BIT);
  return FLGR_RET_NOT_IMPLEMENTED;
}

FLGR_Ret flgr2d_geodesic_reconstruct_dilate_fgUINT8(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask, FLGR_Connexity connexity) {
  GeodesicReconstruction(fgUINT8,FLGR_UINT8,
			 flgr2d_get_nhb_maximum_fgUINT8,
			 flgr_vector_inf_fgUINT8,
			 flgr_anti_raster_slide_recursive_dil_fifo_fgUINT8,
			 flgr_georec_dil_propag_fifo_fgUINT8);
}

FLGR_Ret flgr2d_geodesic_reconstruct_dilate_fgUINT16(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,FLGR_Connexity connexity) {
  GeodesicReconstruction(fgUINT16,FLGR_UINT16,
			 flgr2d_get_nhb_maximum_fgUINT16,
			 flgr_vector_inf_fgUINT16,
			 flgr_anti_raster_slide_recursive_dil_fifo_fgUINT16,
			 flgr_georec_dil_propag_fifo_fgUINT16);
}

FLGR_Ret flgr2d_geodesic_reconstruct_dilate_fgUINT32(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,FLGR_Connexity connexity) {
  GeodesicReconstruction(fgUINT32,FLGR_UINT32,
			 flgr2d_get_nhb_maximum_fgUINT32,
			 flgr_vector_inf_fgUINT32,
			 flgr_anti_raster_slide_recursive_dil_fifo_fgUINT32,
			 flgr_georec_dil_propag_fifo_fgUINT32);
}

FLGR_Ret flgr2d_geodesic_reconstruct_dilate_fgINT8(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,FLGR_Connexity connexity) {
  GeodesicReconstruction(fgINT8,FLGR_INT8,
			 flgr2d_get_nhb_maximum_fgINT8,
			 flgr_vector_inf_fgINT8,
			 flgr_anti_raster_slide_recursive_dil_fifo_fgINT8,
			 flgr_georec_dil_propag_fifo_fgINT8);
}

FLGR_Ret flgr2d_geodesic_reconstruct_dilate_fgINT16(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,FLGR_Connexity connexity) {
  GeodesicReconstruction(fgINT16,FLGR_INT16,
			 flgr2d_get_nhb_maximum_fgINT16,
			 flgr_vector_inf_fgINT16,
			 flgr_anti_raster_slide_recursive_dil_fifo_fgINT16,
			 flgr_georec_dil_propag_fifo_fgINT16);
}

FLGR_Ret flgr2d_geodesic_reconstruct_dilate_fgINT32(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,FLGR_Connexity connexity) {
  GeodesicReconstruction(fgINT32,FLGR_INT32,
			 flgr2d_get_nhb_maximum_fgINT32,
			 flgr_vector_inf_fgINT32,
			 flgr_anti_raster_slide_recursive_dil_fifo_fgINT32,
			 flgr_georec_dil_propag_fifo_fgINT32);
}

FLGR_Ret flgr2d_geodesic_reconstruct_dilate_fgFLOAT32(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,FLGR_Connexity connexity) {
  GeodesicReconstruction(fgFLOAT32,FLGR_FLOAT32,
			 flgr2d_get_nhb_maximum_fgFLOAT32,
			 flgr_vector_inf_fgFLOAT32,
			 flgr_anti_raster_slide_recursive_dil_fifo_fgFLOAT32,
			 flgr_georec_dil_propag_fifo_fgFLOAT32);
}

FLGR_Ret flgr2d_geodesic_reconstruct_dilate_fgFLOAT64(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,FLGR_Connexity connexity) {
  GeodesicReconstruction(fgFLOAT64,FLGR_FLOAT64,
			 flgr2d_get_nhb_maximum_fgFLOAT64,
			 flgr_vector_inf_fgFLOAT64,
			 flgr_anti_raster_slide_recursive_dil_fifo_fgFLOAT64,
			 flgr_georec_dil_propag_fifo_fgFLOAT64);
}






FLGR_Ret flgr2d_geodesic_reconstruct_erode_fgBIT(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask, FLGR_Connexity connexity) {
  flgr_no_define_type_function(FLGR_BIT);
  return FLGR_RET_NOT_IMPLEMENTED;
}

FLGR_Ret flgr2d_geodesic_reconstruct_erode_fgUINT8(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask, FLGR_Connexity connexity) {
  GeodesicReconstruction(fgUINT8,FLGR_UINT8,
			 flgr2d_get_nhb_minimum_fgUINT8,
			 flgr_vector_sup_fgUINT8,
			 flgr_anti_raster_slide_recursive_ero_fifo_fgUINT8,
			 flgr_georec_ero_propag_fifo_fgUINT8);
}

FLGR_Ret flgr2d_geodesic_reconstruct_erode_fgUINT16(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,FLGR_Connexity connexity) {
  GeodesicReconstruction(fgUINT16,FLGR_UINT16,
			 flgr2d_get_nhb_minimum_fgUINT16,
			 flgr_vector_sup_fgUINT16,
			 flgr_anti_raster_slide_recursive_ero_fifo_fgUINT16,
			 flgr_georec_ero_propag_fifo_fgUINT16);
}

FLGR_Ret flgr2d_geodesic_reconstruct_erode_fgUINT32(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,FLGR_Connexity connexity) {
  GeodesicReconstruction(fgUINT32,FLGR_UINT32,
			 flgr2d_get_nhb_minimum_fgUINT32,
			 flgr_vector_sup_fgUINT32,
			 flgr_anti_raster_slide_recursive_ero_fifo_fgUINT32,
			 flgr_georec_ero_propag_fifo_fgUINT32);
}

FLGR_Ret flgr2d_geodesic_reconstruct_erode_fgINT8(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,FLGR_Connexity connexity) {
  GeodesicReconstruction(fgINT8,FLGR_INT8,
			 flgr2d_get_nhb_minimum_fgINT8,
			 flgr_vector_sup_fgINT8,
			 flgr_anti_raster_slide_recursive_ero_fifo_fgINT8,
			 flgr_georec_ero_propag_fifo_fgINT8);
}

FLGR_Ret flgr2d_geodesic_reconstruct_erode_fgINT16(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,FLGR_Connexity connexity) {
  GeodesicReconstruction(fgINT16,FLGR_INT16,
			 flgr2d_get_nhb_minimum_fgINT16,
			 flgr_vector_sup_fgINT16,
			 flgr_anti_raster_slide_recursive_ero_fifo_fgINT16,
			 flgr_georec_ero_propag_fifo_fgINT16);
}

FLGR_Ret flgr2d_geodesic_reconstruct_erode_fgINT32(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,FLGR_Connexity connexity) {
  GeodesicReconstruction(fgINT32,FLGR_INT32,
			 flgr2d_get_nhb_minimum_fgINT32,
			 flgr_vector_sup_fgINT32,
			 flgr_anti_raster_slide_recursive_ero_fifo_fgINT32,
			 flgr_georec_ero_propag_fifo_fgINT32);
}

FLGR_Ret flgr2d_geodesic_reconstruct_erode_fgFLOAT32(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,FLGR_Connexity connexity) {
  GeodesicReconstruction(fgFLOAT32,FLGR_FLOAT32,
			 flgr2d_get_nhb_minimum_fgFLOAT32,
			 flgr_vector_sup_fgFLOAT32,
			 flgr_anti_raster_slide_recursive_ero_fifo_fgFLOAT32,
			 flgr_georec_ero_propag_fifo_fgFLOAT32);
}

FLGR_Ret flgr2d_geodesic_reconstruct_erode_fgFLOAT64(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,FLGR_Connexity connexity) {
  GeodesicReconstruction(fgFLOAT64,FLGR_FLOAT64,
			 flgr2d_get_nhb_minimum_fgFLOAT64,
			 flgr_vector_sup_fgFLOAT64,
			 flgr_anti_raster_slide_recursive_ero_fifo_fgFLOAT64,
			 flgr_georec_ero_propag_fifo_fgFLOAT64);
}






////////////////////////////////////////////////////////////////////////////
/*! Compute Geodesic Reconstruction by dilation
 *
 *  <i>The algorithm used is describe in the book
 *  "Morphological Image Analysis 2nd edition, Pierre Soille, Springer" p195.</i>
 *
 *  @param imgMarker : marker image input/output
 *  @param imgMask : mask image input
 *  @param connexity : connexity (4-connexity,6-connexity,8-connexity)
 *  @returns FLGR_RET_OK, ...
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr2d_geodesic_reconstruct_dilate(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask, FLGR_Connexity connexity) {
  FLGR_Ret ret;

  FLGR_DECLARE_FUNCTION;

  if((imgMarker==NULL) || (imgMask==NULL)){
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  if(imgMarker->spp!=1)  {
    POST_ERROR("Multi Sample Per Pixel not supported\n");
    return FLGR_RET_UNDEFINED_ERROR;
  }

  if((ret=flgr2d_is_data_same_attributes(imgMarker,imgMask,__FUNCTION__))!=FLGR_RET_OK) return ret;

  FLGR_DISPATCH_FUNCTION(FLGR_RET_TYPE_UNKNOWN, imgMarker->type,flgr2d_geodesic_reconstruct_dilate,imgMarker, imgMask, connexity);

}

////////////////////////////////////////////////////////////////////////////
/*! Compute Geodesic Reconstruction by erosion
 *
 *  <i>The algorithm used is describe in the book
 *  "Morphological Image Analysis 2nd edition, Pierre Soille, Springer" p195.</i>
 *
 *  @param imgMarker : marker image input/output
 *  @param imgMask : mask image input
 *  @param connexity : connexity (4-connexity,6-connexity,8-connexity)
 *  @returns FLGR_RET_OK, ...
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr2d_geodesic_reconstruct_erode(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask, FLGR_Connexity connexity) {
  FLGR_Ret ret;

  FLGR_DECLARE_FUNCTION;

  if((imgMarker==NULL) || (imgMask==NULL)){
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }
 
  if(imgMarker->spp!=1)  {
    POST_ERROR("Multi Sample Per Pixel not supported\n");
    return FLGR_RET_UNDEFINED_ERROR;
  }

  if((ret=flgr2d_is_data_same_attributes(imgMarker,imgMask,__FUNCTION__))!=FLGR_RET_OK) return ret;

  FLGR_DISPATCH_FUNCTION(FLGR_RET_TYPE_UNKNOWN,imgMarker->type,flgr2d_geodesic_reconstruct_erode,imgMarker, imgMask, connexity);

}


////////////////////////////////////////////////////////////////////////////
/*! Compute Geodesic Reconstruction by openning
 *  @param imgdest : output image
 *  @param imgsrc : input input
 *  @param nhb : neighborhood definition
 *  @returns FLGR_RET_OK, ...
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr2d_geodesic_reconstruct_open(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *nhb) {
  FLGR_Ret ret;

  FLGR_DECLARE_FUNCTION;

  if((imgdest==NULL) || (imgsrc==NULL) ||(nhb==NULL)){
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  if( (ret=flgr2d_erode(imgdest,imgsrc,nhb)) != FLGR_RET_OK ) return ret;

  return flgr2d_geodesic_reconstruct_dilate(imgdest,imgsrc,nhb->connexity);
}

////////////////////////////////////////////////////////////////////////////
/*! Compute Geodesic Reconstruction by closeing
 *  @param imgdest : output image
 *  @param imgsrc : input input
 *  @param nhb : neighborhood definition
 *  @returns FLGR_RET_OK, ...
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr2d_geodesic_reconstruct_close(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *nhb) {
  FLGR_Ret ret;

  FLGR_DECLARE_FUNCTION;

  if((imgdest==NULL) || (imgsrc==NULL) || (nhb==NULL)){
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  if( (ret=flgr2d_dilate(imgdest,imgsrc,nhb)) != FLGR_RET_OK ) return ret;

  return flgr2d_geodesic_reconstruct_erode(imgdest,imgsrc,nhb->connexity);
}

////////////////////////////////////////////////////////////////////////////
/*! Compute Geodesic Open Tophat
 *  @param imgdest : output image
 *  @param imgsrc : input input
 *  @param nhb : neighborhood definition
 *  @returns FLGR_RET_OK, ...
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr2d_geodesic_reconstruct_open_tophat(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *nhb) {
  FLGR_Ret ret;

  FLGR_DECLARE_FUNCTION;

  if((imgdest==NULL) || (imgsrc==NULL) ||(nhb==NULL)){
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  if( (ret=flgr2d_geodesic_reconstruct_open(imgdest,imgsrc,nhb)) != FLGR_RET_OK ) return ret;

  return flgr2d_arith_sub(imgdest,imgsrc,imgdest);
}

////////////////////////////////////////////////////////////////////////////
/*! Compute Geodesic Close Tophat
 *  @param imgdest : output image
 *  @param imgsrc : input input
 *  @param nhb : neighborhood definition
 *  @returns FLGR_RET_OK, ...
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr2d_geodesic_reconstruct_close_tophat(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Data2D *nhb) {
  FLGR_Ret ret;

  FLGR_DECLARE_FUNCTION;

  if((imgdest==NULL) || (imgsrc==NULL) || (nhb==NULL)){
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  if( (ret=flgr2d_geodesic_reconstruct_close(imgdest,imgsrc,nhb)) != FLGR_RET_OK ) return ret;

  return flgr2d_arith_sub(imgdest,imgdest,imgsrc);
}





////////////////////////////////////////////////////////////////////////////
/*! Compute Regional H-Minima
 *  @param imgdest : output image
 *  @param imgsrc : input input
 *  @param hlevel : level of the minima
 *  @param connexity : string for connexity to use
 *  @returns FLGR_RET_OK, ...
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr2d_regional_hminima(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Vector *hlevel, FLGR_Connexity connexity) {
  FLGR_Ret ret;
  FLGR_Data2D *imgtmp;

  FLGR_DECLARE_FUNCTION;

  if((imgdest==NULL) || (imgsrc==NULL)){
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  imgtmp = flgr2d_create_pixmap_from(imgsrc);
  if(imgtmp == NULL) {
    POST_ERROR("Could not allocate image \n");
    return FLGR_RET_ALLOCATION_ERROR;
  }


  if( (ret=flgr2d_arith_const_addsat_ptr(imgtmp,imgsrc,hlevel)) != FLGR_RET_OK ) return ret;
  if( (ret=flgr2d_geodesic_reconstruct_erode(imgtmp,imgsrc,connexity)) != FLGR_RET_OK ) return ret;

  ret = flgr2d_arith_sub(imgdest,imgtmp,imgsrc);

  flgr2d_destroy(imgtmp);

  return ret;

}



////////////////////////////////////////////////////////////////////////////
/*! Compute Regional H-Maxima
 *  @param imgdest : output image
 *  @param imgsrc : input input
 *  @param hlevel : level of the maxima
 *  @param connexity : string for connexity to use
 *  @returns FLGR_RET_OK, ...
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr2d_regional_hmaxima(FLGR_Data2D *imgdest, FLGR_Data2D *imgsrc, FLGR_Vector *hlevel, FLGR_Connexity connexity) {
  FLGR_Ret ret;
  FLGR_Data2D *imgtmp;

  FLGR_DECLARE_FUNCTION;

  if((imgdest==NULL) || (imgsrc==NULL)){
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  imgtmp = flgr2d_create_pixmap_from(imgsrc);
  if(imgtmp == NULL) {
    POST_ERROR("Could not allocate image \n");
    return FLGR_RET_ALLOCATION_ERROR;
  }


  if( (ret=flgr2d_arith_const_subsat_ptr(imgtmp,imgsrc,hlevel)) != FLGR_RET_OK ) return ret;
  if( (ret=flgr2d_geodesic_reconstruct_dilate(imgtmp,imgsrc,connexity)) != FLGR_RET_OK ) return ret;

  ret = flgr2d_arith_sub(imgdest,imgsrc,imgtmp);

  flgr2d_destroy(imgtmp);

  return ret;

}
















//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// Dual Geodesic Reconstruction
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////



  
////////////////////////////////////////////////////////////////////////////
// Macro for different type flgr2d_raster_slide_window_before_op_TYPE
//////////////////////////////////////////////////////////////////
#define Georec_raster_rec_scan_dual(dtype)				\
  int i,j;								\
  dtype *row_mask, *row_marker;						\
  FLGR_Vector *result, *vec_arith;					\
  FLGR_Data2D *nhbrs;							\
  FLGR_Data2D *nhbEven,*nhbOdd;						\
  FLGR_NhbBox2D *extr;							\
									\
  extr = flgr2d_create_neighbor_box(nhb);				\
									\
  result = flgr_vector_create(extr->spp,extr->type);			\
  vec_arith = flgr_vector_create(extr->spp,extr->type);			\
									\
  nhbEven=flgr2d_create_neighborhood_from(nhb);				\
  nhbOdd=flgr2d_create_neighborhood_from(nhb);				\
									\
  flgr2d_fill_nhbs_for_6_connexity(nhbEven,nhbOdd,nhb,FLGR_NHB_NO_SYM);	\
									\
  flgr2d_apply_raster_scan_method_##dtype(nhbOdd);			\
  flgr2d_apply_raster_scan_method_##dtype(nhbEven);			\
									\
  for(i=0 ; i<imgMarker->size_y ; i++) {				\
    row_marker = (dtype *) imgMarker->array[i];				\
    row_mask = (dtype *) imgMask->array[i];				\
    									\
    for(j=0 ; j<imgMarker->size_x ; j++) {				\
      nhbrs = (((i%2)==1) ? nhbOdd : nhbEven);				\
									\
      flgr2d_get_neighborhood_##dtype(extr,imgMarker,nhbrs,i,j);	\
									\
      if(row_marker[j]<row_mask[j]) {					\
	flgr2d_get_nhb_maximum_##dtype(result,extr);			\
	flgr2d_get_data_vector_no_norm_##dtype(imgMask,i,j,vec_arith);	\
	flgr_vector_inf_##dtype(result,result,vec_arith);		\
	flgr2d_set_data_vector_##dtype(imgMarker,i,j,result);		\
      }else {								\
	flgr2d_get_nhb_minimum_##dtype(result,extr);			\
	flgr2d_get_data_vector_no_norm_##dtype(imgMask,i,j,vec_arith);	\
	flgr_vector_sup_##dtype(result,result,vec_arith);		\
	flgr2d_set_data_vector_##dtype(imgMarker,i,j,result);		\
      }									\
    }									\
  }									\
									\
  flgr2d_destroy(nhbOdd);						\
  flgr2d_destroy(nhbEven);						\
  flgr2d_destroy_neighbor_box(extr);					\
  flgr_vector_destroy(result);						\
  flgr_vector_destroy(vec_arith);					\
  return



void flgr_georec_raster_recursive_dual_fgUINT8(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,FLGR_Data2D *nhb) {
  Georec_raster_rec_scan_dual(fgUINT8);
}

void flgr_georec_raster_recursive_dual_fgUINT16(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,FLGR_Data2D *nhb) {
  Georec_raster_rec_scan_dual(fgUINT16);
}

void flgr_georec_raster_recursive_dual_fgUINT32(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,FLGR_Data2D *nhb) {
  Georec_raster_rec_scan_dual(fgUINT32);
}

void flgr_georec_raster_recursive_dual_fgINT8(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,FLGR_Data2D *nhb) {
  Georec_raster_rec_scan_dual(fgINT8);
}

void flgr_georec_raster_recursive_dual_fgINT16(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,FLGR_Data2D *nhb) {
  Georec_raster_rec_scan_dual(fgINT16);
}

void flgr_georec_raster_recursive_dual_fgINT32(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,FLGR_Data2D *nhb) {
  Georec_raster_rec_scan_dual(fgINT32);
}

void flgr_georec_raster_recursive_dual_fgFLOAT32(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,FLGR_Data2D *nhb) {
  Georec_raster_rec_scan_dual(fgFLOAT32);
}

void flgr_georec_raster_recursive_dual_fgFLOAT64(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,FLGR_Data2D *nhb) {
  Georec_raster_rec_scan_dual(fgFLOAT64);
}







////////////////////////////////////////////////////////////////////////////
// Macro for different type of flgr_georec_dil_back_push_fifo
////////////////////////////////////////////////////////////////////////////
#define Georec_dual_back_push_fifo(dtype)		\
  dtype *pextrMarker;					\
  dtype *pextrMask;					\
  int *list_coord_x, *list_coord_y;			\
  int u,v,i,j,k,l,m,h2,w2;				\
							\
  i=extrMarker->center_coord_y;				\
  j=extrMarker->center_coord_x;				\
							\
  pextrMarker=(dtype *) extrMarker->list_data_val[0];	\
  pextrMask=(dtype *) extrMask->list_data_val[0];	\
  list_coord_x = extrMarker->list_coord_x[0];		\
  list_coord_y = extrMarker->list_coord_y[0];		\
							\
  h2 = extrMarker->nhb_size_y/2;			\
  w2 = extrMarker->nhb_size_x/2;			\
							\
  for(m=0 ; m<extrMarker->size[0] ; m++) {		\
    u=list_coord_y[m];					\
    v=list_coord_x[m];					\
    k=i+u-h2;						\
    l=j+v-w2;						\
							\
    if( (pextrMarker[m] < pixCenter) &&			\
	(pextrMarker[m] < pextrMask[m]) ) {		\
      flgr_static_fifo_write(fifo,k,l);			\
    }else if( (pextrMarker[m] > pixCenter ) &&		\
	      (pextrMarker[m] > pextrMask[m]) ) {	\
      flgr_static_fifo_write(fifo,k,l);			\
    }							\
							\
  }							\
  return



void flgr_georec_dual_back_push_fifo_fgUINT8(FLGR_StaticFifo *fifo, FLGR_NhbBox2D *extrMarker,
					     FLGR_NhbBox2D *extrMask, fgUINT8 pixCenter) {
  Georec_dual_back_push_fifo(fgUINT8);
}

void flgr_georec_dual_back_push_fifo_fgUINT16(FLGR_StaticFifo *fifo, FLGR_NhbBox2D *extrMarker,
					      FLGR_NhbBox2D *extrMask, fgUINT16 pixCenter) {
  Georec_dual_back_push_fifo(fgUINT16);
}

void flgr_georec_dual_back_push_fifo_fgUINT32(FLGR_StaticFifo *fifo, FLGR_NhbBox2D *extrMarker,
					      FLGR_NhbBox2D *extrMask, fgUINT32 pixCenter) {
  Georec_dual_back_push_fifo(fgUINT32);
}

void flgr_georec_dual_back_push_fifo_fgINT8(FLGR_StaticFifo *fifo, FLGR_NhbBox2D *extrMarker,
					    FLGR_NhbBox2D *extrMask, fgINT8 pixCenter) {
  Georec_dual_back_push_fifo(fgINT8);
}

void flgr_georec_dual_back_push_fifo_fgINT16(FLGR_StaticFifo *fifo, FLGR_NhbBox2D *extrMarker,
					     FLGR_NhbBox2D *extrMask, fgINT16 pixCenter) {
  Georec_dual_back_push_fifo(fgINT16);
}

void flgr_georec_dual_back_push_fifo_fgINT32(FLGR_StaticFifo *fifo, FLGR_NhbBox2D *extrMarker,
					     FLGR_NhbBox2D *extrMask, fgINT32 pixCenter) {
  Georec_dual_back_push_fifo(fgINT32);
}

void flgr_georec_dual_back_push_fifo_fgFLOAT32(FLGR_StaticFifo *fifo, FLGR_NhbBox2D *extrMarker,
					       FLGR_NhbBox2D *extrMask, fgFLOAT32 pixCenter) {
  Georec_dual_back_push_fifo(fgFLOAT32);
}

void flgr_georec_dual_back_push_fifo_fgFLOAT64(FLGR_StaticFifo *fifo, FLGR_NhbBox2D *extrMarker,
					       FLGR_NhbBox2D *extrMask, fgFLOAT64 pixCenter) {
  Georec_dual_back_push_fifo(fgFLOAT64);
}




////////////////////////////////////////////////////////////////////////////
// Macro for different type of
////////////////////////////////////////////////////////////////////////////
#define Georec_back_rec_scan_dual_Fifo(dtype)				\
  int i,j;								\
  dtype *row_mask, *row_marker;						\
  FLGR_Vector *result, *vec_arith;					\
  FLGR_Data2D *nhbars;							\
  FLGR_Data2D *nhbEven,*nhbOdd;						\
  FLGR_NhbBox2D *maskextr,*extr;					\
									\
  extr = flgr2d_create_neighbor_box(nhb);				\
  maskextr = flgr2d_create_neighbor_box(nhb);				\
									\
  result = flgr_vector_create(extr->spp,extr->type);			\
  vec_arith = flgr_vector_create(extr->spp,extr->type);			\
									\
  nhbEven=flgr2d_create_neighborhood_from(nhb);				\
  nhbOdd=flgr2d_create_neighborhood_from(nhb);				\
									\
  flgr2d_fill_nhbs_for_6_connexity(nhbEven,nhbOdd,nhb,FLGR_NHB_NO_SYM);	\
									\
  flgr2d_apply_anti_raster_scan_method_##dtype(nhbOdd);			\
  flgr2d_apply_anti_raster_scan_method_##dtype(nhbEven);		\
									\
  for(i=imgMarker->size_y-1 ; i>=0 ; i--) {				\
    row_marker = (dtype *) imgMarker->array[i];				\
    row_mask = (dtype *) imgMask->array[i];				\
									\
    for(j=imgMarker->size_x-1 ; j>=0 ; j--) {				\
									\
      nhbars = (((i%2)==1) ? nhbOdd : nhbEven);				\
									\
      flgr2d_get_neighborhood_##dtype(extr,imgMarker,nhbars, i, j);	\
      flgr2d_get_neighborhood_##dtype(maskextr,imgMask, nhbars, i, j);	\
      if(row_marker[j]<row_mask[j]) {					\
	flgr2d_get_nhb_maximum_##dtype(result,extr);			\
	flgr2d_get_data_vector_no_norm_##dtype(imgMask,i,j,vec_arith);	\
	flgr_vector_inf_##dtype(result,result,vec_arith);		\
	flgr2d_set_data_vector_##dtype(imgMarker,i,j,result);		\
      }else {								\
	flgr2d_get_nhb_minimum_##dtype(result,extr);			\
	flgr2d_get_data_vector_no_norm_##dtype(imgMask,i,j,vec_arith);	\
	flgr_vector_sup_##dtype(result,result,vec_arith);		\
	flgr2d_set_data_vector_##dtype(imgMarker,i,j,result);		\
      }									\
									\
      flgr_georec_dual_back_push_fifo_##dtype(fifo,extr,maskextr,row_marker[j]); \
									\
    }									\
  }									\
									\
  flgr2d_destroy(nhbOdd);						\
  flgr2d_destroy(nhbEven);						\
									\
  flgr2d_destroy_neighbor_box(extr);					\
  flgr2d_destroy_neighbor_box(maskextr);				\
  flgr_vector_destroy(result);						\
  flgr_vector_destroy(vec_arith);					\
   									\
  return


void flgr_georec_back_recursive_dual_fifo_fgUINT8(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
						  FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {
  Georec_back_rec_scan_dual_Fifo(fgUINT8);
}

void flgr_georec_back_recursive_dual_fifo_fgUINT16(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
						   FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {
  Georec_back_rec_scan_dual_Fifo(fgUINT16);
}

void flgr_georec_back_recursive_dual_fifo_fgUINT32(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
						   FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {
  Georec_back_rec_scan_dual_Fifo(fgUINT32);
}

void flgr_georec_back_recursive_dual_fifo_fgINT8(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
						 FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {
  Georec_back_rec_scan_dual_Fifo(fgINT8);
}

void flgr_georec_back_recursive_dual_fifo_fgINT16(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
						  FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {
  Georec_back_rec_scan_dual_Fifo(fgINT16);
}

void flgr_georec_back_recursive_dual_fifo_fgINT32(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
						  FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {
  Georec_back_rec_scan_dual_Fifo(fgINT32);
}

void flgr_georec_back_recursive_dual_fifo_fgFLOAT32(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
						    FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {
  Georec_back_rec_scan_dual_Fifo(fgFLOAT32);
}

void flgr_georec_back_recursive_dual_fifo_fgFLOAT64(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
						    FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {
  Georec_back_rec_scan_dual_Fifo(fgFLOAT64);
}





////////////////////////////////////////////////////////////////////////////
// Different type of flgr_georec_dual_push_fifo (dtype)
////////////////////////////////////////////////////////////////////////////
#define Georec_Dual_Push_Fifo(dtype)					\
  dtype *pextrMarker;							\
  dtype *pextrMask;							\
  int u,v,i,j,k,l,m,h2,w2;						\
  int *list_x, *list_y;							\
  dtype pixCenter;							\
  dtype pixCenterMask;							\
  dtype maxi,mini;							\
									\
  i=extrmarker->center_coord_y;						\
  j=extrmarker->center_coord_x;						\
									\
  pextrMarker=(dtype *) extrmarker->list_data_val[0];			\
  pextrMask=(dtype *) extrmask->list_data_val[0];			\
  list_x = (int *) extrmarker->list_coord_x[0];				\
  list_y = (int *) extrmarker->list_coord_y[0];				\
									\
  flgr_vector_get_element(extrmarker->center_data_val,0,&pixCenter);	\
  flgr_vector_get_element(extrmask->center_data_val,0,&pixCenterMask);	\
									\
  w2=extrmarker->nhb_size_x/2;						\
  h2=extrmarker->nhb_size_y/2;						\
									\
  for(m=0 ; m<extrmarker->size[0] ; m++) {				\
    u=list_y[m];							\
    v=list_x[m];							\
    k=i+u-h2;								\
    l=j+v-w2;								\
									\
    if(pextrMarker[m]<pixCenterMask) {					\
      if( (pextrMarker[m]<pixCenter) &&					\
	  (pextrMarker[m]<pextrMask[m]) ) {				\
	mini=FLGR_MIN(pixCenter,pextrMask[m]);				\
	flgr2d_set_data_array_##dtype((dtype**) imgMarker->array,k,l,mini); \
	flgr_static_fifo_write(fifo,k,l);					\
      }									\
									\
    }else {								\
      if( (pextrMarker[m]>pixCenter) &&					\
	  (pextrMarker[m]>pextrMask[m]) ) {				\
	maxi=FLGR_MAX(pixCenter,pextrMask[m]);				\
	flgr2d_set_data_array_##dtype((dtype**) imgMarker->array,k,l,maxi); \
	flgr_static_fifo_write(fifo,k,l);					\
      }									\
    }									\
  }									\
  return


void flgr_georec_dual_push_fifo_fgUINT8(FLGR_StaticFifo *fifo,
					FLGR_NhbBox2D *extrmarker,
					FLGR_NhbBox2D *extrmask, FLGR_Data2D *imgMarker) {
  Georec_Dual_Push_Fifo(fgUINT8);
}

void flgr_georec_dual_push_fifo_fgUINT16(FLGR_StaticFifo *fifo,
					 FLGR_NhbBox2D *extrmarker,
					 FLGR_NhbBox2D *extrmask, FLGR_Data2D *imgMarker) {
  Georec_Dual_Push_Fifo(fgUINT16);
}

void flgr_georec_dual_push_fifo_fgUINT32(FLGR_StaticFifo *fifo,
					 FLGR_NhbBox2D *extrmarker,
					 FLGR_NhbBox2D *extrmask, FLGR_Data2D *imgMarker) {
  Georec_Dual_Push_Fifo(fgUINT32);
}

void flgr_georec_dual_push_fifo_fgINT8(FLGR_StaticFifo *fifo,
				       FLGR_NhbBox2D *extrmarker,
				       FLGR_NhbBox2D *extrmask, FLGR_Data2D *imgMarker) {
  Georec_Dual_Push_Fifo(fgINT8);
}

void flgr_georec_dual_push_fifo_fgINT16(FLGR_StaticFifo *fifo,
					FLGR_NhbBox2D *extrmarker,
					FLGR_NhbBox2D *extrmask, FLGR_Data2D *imgMarker) {
  Georec_Dual_Push_Fifo(fgINT16);
}

void flgr_georec_dual_push_fifo_fgINT32(FLGR_StaticFifo *fifo,
					FLGR_NhbBox2D *extrmarker,
					FLGR_NhbBox2D *extrmask, FLGR_Data2D *imgMarker) {
  Georec_Dual_Push_Fifo(fgINT32);
}

void flgr_georec_dual_push_fifo_fgFLOAT32(FLGR_StaticFifo *fifo,
					  FLGR_NhbBox2D *extrmarker,
					  FLGR_NhbBox2D *extrmask, FLGR_Data2D *imgMarker) {
  Georec_Dual_Push_Fifo(fgFLOAT32);
}

void flgr_georec_dual_push_fifo_fgFLOAT64(FLGR_StaticFifo *fifo,
					  FLGR_NhbBox2D *extrmarker,
					  FLGR_NhbBox2D *extrmask, FLGR_Data2D *imgMarker) {
  Georec_Dual_Push_Fifo(fgFLOAT64);
}





void flgr_georec_dual_propag_fifo_fgUINT8(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
					  FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {
  Georec_propag_fifo_cont(fgUINT8,flgr_georec_dual_push_fifo_fgUINT8);
}

void flgr_georec_dual_propag_fifo_fgUINT16(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
					   FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {
  Georec_propag_fifo_cont(fgUINT16,flgr_georec_dual_push_fifo_fgUINT16);
}


void flgr_georec_dual_propag_fifo_fgUINT32(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
					   FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {
  Georec_propag_fifo_cont(fgUINT32,flgr_georec_dual_push_fifo_fgUINT32);
}

void flgr_georec_dual_propag_fifo_fgINT8(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
					 FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {
  Georec_propag_fifo_cont(fgINT8,flgr_georec_dual_push_fifo_fgINT8);
}

void flgr_georec_dual_propag_fifo_fgINT16(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
					  FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {
  Georec_propag_fifo_cont(fgINT16,flgr_georec_dual_push_fifo_fgINT16);

}

void flgr_georec_dual_propag_fifo_fgINT32(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
					  FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {
  Georec_propag_fifo_cont(fgINT32,flgr_georec_dual_push_fifo_fgINT32);

}

void flgr_georec_dual_propag_fifo_fgFLOAT32(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
					    FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {
  Georec_propag_fifo_cont(fgFLOAT32,flgr_georec_dual_push_fifo_fgFLOAT32);

}

void flgr_georec_dual_propag_fifo_fgFLOAT64(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask,
					    FLGR_Data2D *nhb, FLGR_StaticFifo *fifo) {
  Georec_propag_fifo_cont(fgFLOAT64,flgr_georec_dual_push_fifo_fgFLOAT64);

}



////////////////////////////////////////////////////////////////////////////
// Macro for different type of flgr2d_geodesic_Reconstruction
////////////////////////////////////////////////////////////////////////////
#define GeodesicReconstructionDual(dtype,dtypename)			\
									\
  FLGR_Data2D *nhb;							\
  FLGR_StaticFifo *fifo;							\
  FLGR_DECLARE_FUNCTION;						\
									\
  nhb = flgr2d_create_neighborhood_from_connexity(imgMarker->spp,dtypename,connexity); \
									\
  if(nhb==NULL) return FLGR_RET_ALLOCATION_ERROR;			\
									\
  fifo = flgr_static_fifo_init(imgMarker->size_y,imgMarker->size_x);		\
									\
  flgr_georec_raster_recursive_dual_##dtype(imgMarker,imgMask,nhb);	\
  flgr_georec_back_recursive_dual_fifo_##dtype(imgMarker,		\
					       imgMask,nhb,fifo);  	\
  flgr_georec_dual_propag_fifo_##dtype(imgMarker,imgMask,nhb,fifo);	\
									\
  flgr2d_destroy(nhb);							\
  flgr_static_fifo_destroy(fifo);						\
									\
  return FLGR_RET_OK



FLGR_Ret flgr2d_geodesic_reconstruct_dual_fgBIT(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask, FLGR_Connexity connexity) {
  flgr_no_define_type_function(FLGR_BIT);
  return FLGR_RET_NOT_IMPLEMENTED;
}

FLGR_Ret flgr2d_geodesic_reconstruct_dual_fgUINT8(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask, FLGR_Connexity connexity) {
  GeodesicReconstructionDual(fgUINT8,FLGR_UINT8);
}

FLGR_Ret flgr2d_geodesic_reconstruct_dual_fgUINT16(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask, FLGR_Connexity connexity) {
  GeodesicReconstructionDual(fgUINT16,FLGR_UINT16);
}

FLGR_Ret flgr2d_geodesic_reconstruct_dual_fgUINT32(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask, FLGR_Connexity connexity) {
  GeodesicReconstructionDual(fgUINT32,FLGR_UINT32);
}

FLGR_Ret flgr2d_geodesic_reconstruct_dual_fgINT8(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask, FLGR_Connexity connexity) {
  GeodesicReconstructionDual(fgINT8,FLGR_INT8);
}

FLGR_Ret flgr2d_geodesic_reconstruct_dual_fgINT16(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask, FLGR_Connexity connexity) {
  GeodesicReconstructionDual(fgINT16,FLGR_INT16);
}

FLGR_Ret flgr2d_geodesic_reconstruct_dual_fgINT32(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask, FLGR_Connexity connexity) {
  GeodesicReconstructionDual(fgINT32,FLGR_INT32);
}

FLGR_Ret flgr2d_geodesic_reconstruct_dual_fgFLOAT32(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask, FLGR_Connexity connexity) {
  GeodesicReconstructionDual(fgFLOAT32,FLGR_FLOAT32);
}

FLGR_Ret flgr2d_geodesic_reconstruct_dual_fgFLOAT64(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask, FLGR_Connexity connexity) {
  GeodesicReconstructionDual(fgFLOAT64,FLGR_FLOAT64);
}


////////////////////////////////////////////////////////////////////////////
/*! Compute Geodesic Dual Reconstruction
 *
 *  Reconstruct by erosion or dilation. Depending of each pixel mask position regarding each pixel marker position
 * 
 *  <i>The algorithm used is describe in the book
 *  "Morphological Image Analysis 2nd edition, Pierre Soille, Springer" p195.</i>
 *
 *  @param imgMarker : marker image input/output
 *  @param imgMask : mask image input
 *  @param connexity : connexity (4-connexity,6-connexity,8-connexity)
 *  @returns FLGR_RET_OK, ...
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr2d_geodesic_reconstruct_dual(FLGR_Data2D *imgMarker, FLGR_Data2D *imgMask, FLGR_Connexity connexity) {
  FLGR_Ret ret;

  FLGR_DECLARE_FUNCTION;

  if((imgMarker==NULL) || (imgMask==NULL)){
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  if(imgMarker->spp!=1)  {
    POST_ERROR("Multi Sample Per Pixel not supported\n");
    return FLGR_RET_UNDEFINED_ERROR;
  }

  if((ret=flgr2d_is_data_same_attributes(imgMarker,imgMask,__FUNCTION__))!=FLGR_RET_OK) return ret;

  FLGR_DISPATCH_FUNCTION(FLGR_RET_TYPE_UNKNOWN,imgMarker->type,flgr2d_geodesic_reconstruct_dual,imgMarker, imgMask, connexity);

}


//! @}



